package com.blogspot.codingandmore.jboss.filter;

import org.jboss.ejb.plugins.AbstractInterceptor;
import org.jboss.invocation.Invocation;
import org.jboss.logging.Logger;

import com.blogspot.codingandmore.jboss.filter.properties.FilterProperties;

/**
 * a simple interceptor for jboss
 * 
 * @author wohlgemuth
 */
public class SessionInterceptor extends AbstractInterceptor {

	private final Logger logger = Logger.getLogger(getClass());

	private boolean acceptedLastRequest = false;
	private boolean acceptedLastRequestByDefault = false;

	public boolean isAcceptedLastRequestByDefault() {
		return acceptedLastRequestByDefault;
	}

	public boolean isAcceptedLastRequest() {
		return acceptedLastRequest;
	}

	public Logger getLogger() {
		return logger;
	}

	@Override
	public void create() throws Exception {
		logger.debug("create...");
		super.create();
	}

	@Override
	public void destroy() {
		logger.debug("destroy...");
		super.destroy();
	}

	@Override
	public Object invoke(final Invocation mi) throws Exception {

		try {
			acceptedLastRequest = false;
			acceptedLastRequestByDefault = false;

			String ip = Thread.currentThread().getName();

			if (ip.indexOf("http") > -1) {
				logger.debug("html request...");
				String[] elements = ip.split("-");
				ip = elements[1];
			}
			else if (ip.indexOf("") > -1) {
				if (ip.indexOf("[") > -1 && ip.indexOf("]") > -1) {
					logger.debug("ejb request...");
					int begin = ip.indexOf('[') + 1;
					int end = ip.indexOf(']');
					ip = ip.substring(begin, end);
				}

			}
			else {
				logger.warn("unknown ip layout!");
			}

			if (ip.indexOf(":") > -1) {
				String temp = ip.substring(0, ip.indexOf(":"));
				logger.info(ip + " -> " + temp);
				ip = temp;
			}
			ip = ip.trim();
			logger.info("request from ip: " + ip);

			PropertieFactory fact = PropertieFactory.getInstance();

			if (ip.equals("0.0.0.0")) {
				logger.info("same host, we accept this by default");
				acceptedLastRequest = true;
				return super.invoke(mi);
			}
			else if (ip.equals("127.0.0.1")) {
				acceptedLastRequest = true;

				logger.info("same host, we accept this by default");
				return super.invoke(mi);
			}
			else {
				logger.info("checking properties for this ip: " + ip);

				for (FilterProperties propertie : fact.getProperties()) {
					logger.debug("pattern: " + propertie.getIp() + " - " + propertie.isPermit());
					boolean permit = ip.matches(propertie.getIp());
					logger.debug("matches: " + permit);

					if (ip.equals(propertie.getIp())) {
						return acceptResult(mi, ip, propertie);
					}
					else if (permit) {
						return acceptResult(mi, ip, propertie);
					}
					else {
						// accepts complete subnets

						if (ip.matches("\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b") && propertie.getIp().matches("\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b")) {

							String[] ipParamas = ip.trim().split("\\.");
							String[] patParams = propertie.getIp().trim().split("\\.");

							boolean accept = false;

							if (ipParamas.length == patParams.length) {

								if (accept == false) {

									for (int i = 0; i < ipParamas.length; i++) {
										if (i == ipParamas.length - 1) {

											if (patParams[i].equals("0")) {
												accept = true;
											}
										}
										else {

											if (patParams[i].equals(ipParamas[i]) == false) {
												i = 2 * ipParamas.length;
											}
										}

									}
								}
							}

							if (accept == true) {
								logger.debug("accepted a subnet");
								return acceptResult(mi, ip, propertie);
							}
						}

					}
				}

				if (fact.permitByDefault()) {
					acceptedLastRequest = true;
					acceptedLastRequestByDefault = true;

					logger.info("we permited this ip by default: " + ip);
					return super.invoke(mi);
				}
				else {
					logger.warn("ip rejected by default: " + ip);
				}
			}
			throw new Exception("no access defined for ip: " + ip);

		}
		catch (RuntimeException e) {
			e.printStackTrace();
			throw new Exception("access is rejected because of an internal exception: " + e.getMessage());

		}

	}

	private Object acceptResult(final Invocation mi, String ip, FilterProperties propertie) throws Exception {

		System.out.println(propertie);
		if (propertie.isPermit() == true) {
			acceptedLastRequest = true;

			logger.info("accepted ip: " + ip);
			try {
				return super.invoke(mi);
			}
			catch (NullPointerException e) {
				logger.warn("the next interceptor caused a null pointer exception, but since this interceptor worked we move on!");
				return true;
			}
		}
		else {
			acceptedLastRequest = false;

			logger.warn("refused ip: " + ip);
			throw new Exception("ip refused: " + ip);
		}
	}

}
